﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using AllInOnePluginBL.Helpers;
using PluginDB;

namespace AllInOnePluginBL.SiteScrappers
{
    /// <summary>
    /// Summary description for TopDownMeParserJob
    /// </summary>
    public class TopDownMeParserJob : BaseSiteScrapper
    {
        #region Private Members
        private const string DEFAULT_URL = "http://www.topdown.me/";
        private const string MOVIES_URL = "http://www.topdown.me/?page=viewcat&catid=2&p={0}";
        private const string SERIES_URL = "http://www.topdown.me/?page=viewcat&catid=3&p={0}";
        private const string NAME = "TopDown.Me";
        #endregion

        #region Ctor
        public TopDownMeParserJob() : base(NAME)
        {
        } 
        #endregion

        #region Override Methods
        public override void Execute(int pagesToScan)
        {
            _log.Info(string.Format("Start Executing TopDownMeParserJob at {0}", DateTime.Now.ToString("r")));

            try
            {
                ScanForMovies(pagesToScan);
            }
            catch (Exception exception)
            {
                _log.ErrorException("Error while ScanForMovies", exception);
            }

            try
            {
                ScanForSeries(pagesToScan);
            }
            catch (Exception exception)
            {
                _log.ErrorException("Error while ScanForSeries", exception);
            }

            _log.Info(string.Format("End Executing TopDownMeParserJob at {0}", DateTime.Now.ToString("r")));
        } 
        #endregion

        #region Private Methods
        private void ScanForMovies(int pagesToScan)
        {
            var lastPageNumber = GetMoviesLastPageNumber();
            pagesToScan = (pagesToScan == 0 || pagesToScan > lastPageNumber) ? lastPageNumber : pagesToScan;

            for (var i = pagesToScan; i > 0; i--)
            {
                var url = string.Format(MOVIES_URL, i);
                this.GetMovies(url);
            }
        }

        private int GetMoviesLastPageNumber()
        {
            try
            {
                const string PAGES_REGEX = "<a href=\"\\?page=viewcat&amp;catid=2&amp;p=(.+?)\">";

                var url = string.Format(MOVIES_URL, 1);
                var pageContent = Utils.GetPage(url, Encoding.UTF8);

                var matches = Regex.Matches(pageContent, PAGES_REGEX, RegexOptions.Singleline);
                if (matches.Count == 0)
                    throw new Exception("Get find page regex");

                return int.Parse(matches[matches.Count - 1].Groups[1].Value);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception in GetMoviesLastPageNumber: {0}", ex.Message);
                return 0;
            }
        }

        private void ScanForSeries(int pagesToScan)
        {
            var lastPageNumber = GetSeriesLastPageNumber();
            pagesToScan = (pagesToScan == 0 || pagesToScan > lastPageNumber) ? lastPageNumber : pagesToScan;

            for (var i = pagesToScan; i > 0; i--)
            {
                var url = string.Format(SERIES_URL, i);
                this.GetMovies(url);
            }
        }

        private int GetSeriesLastPageNumber()
        {
            try
            {
                const string PAGES_REGEX = "<a href=\"\\?page=viewcat&amp;catid=3&amp;p=(.+?)\">";

                var url = string.Format(SERIES_URL, 1);
                var pageContent = Utils.GetPage(url, Encoding.UTF8);

                var matches = Regex.Matches(pageContent, PAGES_REGEX, RegexOptions.Singleline);
                if (matches.Count == 0)
                    throw new Exception("Get find page regex");

                return int.Parse(matches[matches.Count - 1].Groups[1].Value);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception in GetSeriesLastPageNumber: {0}", ex.Message);
                return 0;
            }
        }

        private void GetMovies(string url)
        {
            try
            {
                var page = Utils.GetPage(url, Encoding.GetEncoding("windows-1255"));

                const string moviesContainerExpression = "<table width=\"540\" style=\"color:#ffffff\" cellpadding=\"0\" cellspacing=\"0\">.*?<td rowspan=\"2\"><a href=\"(.+?)\"><img src=\"(.+?)\" alt=\"(.+?)\".*?</td>";
                var matches = Regex.Matches(page, moviesContainerExpression, RegexOptions.Singleline);
                foreach (Match match in matches)
                {
                    var moviePageLink = DEFAULT_URL + match.Groups[1].Value;
                    var movieTitle = match.Groups[3].Value;

                    if (_pluginDBHandler.IsVideoExists(moviePageLink))
                        continue;

                    var video = FillMovieInfo(movieTitle, moviePageLink);

                    if (video.Links.Count == 0)
                    {
                        _log.Debug("{0} Has no links. not saving it", movieTitle);
                        continue;
                    }

                    _pluginDBHandler.AddNewVideo(video);
                }
            }
            catch (Exception ex)
            {
                _log.ErrorException(string.Format("Exception in TopDownMeParser::GetMovies:{0}", url), ex);
            }
        }

        private PluginVideoInfo FillMovieInfo(string movieName, string moviePageLink)
        {
            var pageContent = Utils.GetPage(moviePageLink, Encoding.GetEncoding("windows-1255"));

            #region Get Plot and Image
            string plot, imageUrl;
            GetPlotAndImage(pageContent, out plot, out imageUrl);
            #endregion

            var video = new PluginVideoInfo
            {
                VideoName = movieName,
                PluginUrl = moviePageLink,
                SiteName = NAME,
                Categories = new List<string> { Common.GENERAL_CATEGORY_NAME },
                ImageUrl = imageUrl,
                Plot = plot
            };

            #region Get Links
            var links = Utils.GetMovieLinks(pageContent);
            foreach (var link in links)
            {
                video.Links.Add(new PluginVideoInfo.Link
                {
                    LinkURL = link,
                    SourceName = GetLinkSource(link)
                });
            }
            return video;
            #endregion
        }

        public static void GetPlotAndImage(string pageContent, out string plot, out string image)
        {
            try
            {
                const string imageRegEx = "<table  height=\"(.*?)\" width=\"(.*?)\" align=\"right\" cellpadding=\"5\" cellspacing=\"5\">.*?<img src=\"(.+?)\".*?>";
                const string plotRegEx = "</td></tr><td style=\"padding-top:5px;\">.*?<tr><td.*?>(.+?)></td>";

                var imageMatch = Regex.Match(pageContent, imageRegEx, RegexOptions.Singleline);
                image = imageMatch.Groups[3].Value;

                var plotMatch = Regex.Match(pageContent, plotRegEx, RegexOptions.Singleline);
                plot = plotMatch.Groups[1].Value;

                plot = plot.Trim()
                    .Replace("<a>", string.Empty)
                    .Replace("</a>", string.Empty)
                    .Replace("<", string.Empty)
                    .Replace(">", string.Empty)
                    .Replace("/", string.Empty)
                    .Replace("td", string.Empty)
                    .Replace("tr", string.Empty)
                    .Replace("span", string.Empty)
                    .Replace("strong", string.Empty)
                    .Replace("&nbsp;", string.Empty)
                    .Replace("p", string.Empty)
                    .Replace("\r", string.Empty)
                    .Replace("\n", string.Empty)
                    .Replace("class=\"details\"", string.Empty)
                    .Replace("<div class=\"generalInfoFieldLeft expand\" style=\"min-height: 210px;\">", string.Empty);
                var endIndex = plot.IndexOf("<");
                if (endIndex == -1) return;

                plot = plot.Substring(0, endIndex).Trim();
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception in GetPlotAndImage: {0}", ex.Message);
                plot = string.Empty;
                image = string.Empty;
            }
        }

        private string GetLinkSource(string link)
        {
            const string expression = @"^([a-zA-Z]+:\/\/)?([^\/]+)\/.*?$";
            var match = Regex.Match(link, expression, RegexOptions.Singleline);
            if (match.Success)
            {
                var list = match.Groups[2].Value.Split('.');
                if (list[0] == "www")
                    return list[1];
                return list[0];

            }
            return string.Empty;
        }
        #endregion
    }
}